home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / pctjag86.arc / ATPERF.C < prev    next >
Text File  |  1986-05-29  |  13KB  |  413 lines

  1. /*
  2.  * ATPERF -- PC Tech Journal AT Hardware Performance Test
  3.  *
  4.  * Version 1.00
  5.  * Last modified 05/17/86
  6.  * Copyright (c) 1986, PC Tech Journal
  7.  * Program by: Paul Pierce, Ted Forgeron, Steven Armbrust
  8.  *
  9.  * Measures clock rates and memory speeds
  10.  * of AT compatible computers.
  11.  */
  12.  
  13. #define vars 14
  14.  
  15. /* Timer rate in MHz */
  16. #define TIMER2_RATE 1.193180
  17.  
  18. /* Number of processor clocks in a multiply instruction */
  19. #define MULCLKS 21
  20.  
  21. /* Overhead in the multiply test */
  22. #define MULOVH ( 15 + 14*count/100 )
  23.  
  24. /* Overhead in the mov instruction test */
  25. #define MOVOVH ( clktime * (15 + 14*count/100) )
  26.  
  27. /* Overhead in the stringop tests */
  28. #define STROVH ( clktime * 8 )
  29.  
  30. /* Number of numeric processor clocks in a FP divide */
  31. #define FPCLKS 203
  32.  
  33. /* Processor overhead in the FP divide test */
  34. #define FPOVH ( clktime * 9 * FPCOUNT )
  35.  
  36. /* Count for most tests */
  37. #define COUNT 1000
  38.  
  39. /* Count for the f. p. divide test */
  40. #define FPCOUNT 100
  41.  
  42. /* Number of trials for each test */
  43. #define TRIALS 100
  44.  
  45.  
  46. double clkrate; /* Processor clock rate, MHz */
  47. double clktime; /* Processor clock period, usec */
  48. double fprate;  /* FP processor clock rate, MHz */
  49. double fpacc;   /* FP processor clock period accumulator */
  50. int emmok;      /* Set if extended memory is present */
  51. int ndpok;      /* Set if math coprocessor is present */
  52.  
  53.  
  54.  
  55. /*
  56.  * Main program.
  57.  */
  58.  
  59. main(argc, argv)
  60.         int     argc;
  61.         char    **argv;
  62. {
  63.         double raw, brw, wrw;   /* Variables for raw data */
  64.         double acctime[vars];   /* Accumulators for speeds */
  65.         int count;              /* Number of ops per trial */
  66.         int trials;             /* Number of repetitions */
  67.         register int i;
  68.  
  69.         count = COUNT;
  70.         trials = TRIALS;
  71.  
  72.         /*
  73.          * Measure the clock rate by executing
  74.          * multiply instructions.  Each multiply
  75.          * takes a fixed number of clock cycles.
  76.          */
  77.  
  78.         clktime = 0;
  79.         for (i = 0; i < trials; i++) {
  80.  
  81.                 /*
  82.                  * Obtain the number of clock ticks for
  83.                  * "count" multiplies.
  84.                  */
  85.  
  86.                 raw = multime(count);
  87.  
  88.                 /*
  89.                  * Accumulate the clock time in microseconds
  90.                  * by adjusting for the timer rate,
  91.                  * number of clocks per multiply,
  92.                  * instruction count, and test overhead.
  93.                  */
  94.  
  95.                 clktime +=  raw /
  96.                         (TIMER2_RATE * (MULCLKS*count + MULOVH));
  97.         }
  98.  
  99.         /*
  100.          * Calculate the average clock period by dividing by
  101.          * the number of trials.  The clock rate is the
  102.          * inverse of the clock period.
  103.          */
  104.  
  105.         clktime /= trials;
  106.         clkrate = 1.0/clktime;
  107.  
  108.         /*
  109.          * Determine whether there a math coprocessor
  110.          * in the system.
  111.          */
  112.  
  113.         ndpok = ndp_present();
  114.  
  115.         /*
  116.          * Determine whether there is extended memory in the
  117.          * system and allocate a piece of it for testing.
  118.          */
  119.  
  120.         emmok = (setup_emm() == 0);
  121.  
  122.         /*
  123.          * Clear all of the memory speed accumulators.
  124.          */
  125.  
  126.         for (i = 0; i < vars; i++)
  127.                 acctime[i] = 0;
  128.  
  129.         /*
  130.          * Do the memory speed tests.
  131.          */
  132.  
  133.         for (i = 0; i < trials; i++) {
  134.  
  135.                 /*
  136.                  * Obtain the number of timer ticks for
  137.                  * "count" mov instructions, which are
  138.                  * limited by memory fetch time.
  139.                  */
  140.  
  141.                 raw = wmovtime(count);
  142.  
  143.                 /*
  144.                  * Accumulate the number of microseconds
  145.                  * per instruction fetch by adjusting for
  146.                  * the timer rate, test overhead, and
  147.                  * instruction count.
  148.                  */
  149.  
  150.                 acctime[8] +=
  151.                         (raw / TIMER2_RATE - MOVOVH) / count;
  152.  
  153.                 /*
  154.                  * In a similar manner, measure the
  155.                  * RAM byte write time using the stos
  156.                  * instruction.
  157.                  */
  158.  
  159.                 brw = bstotime(count);
  160.                 acctime[2] += brw/(TIMER2_RATE*count);
  161.  
  162.                 /*
  163.                  * Calculate memory read time by
  164.                  * measuring movs instructions
  165.                  * (read followed by write) and
  166.                  * subtracting the write time
  167.                  * measured above.
  168.                  */
  169.  
  170.                 raw = bmvstime(count) - brw;
  171.                 acctime[0] += raw/(TIMER2_RATE*count);
  172.  
  173.                 /*
  174.                  * Calculate ROM read time by
  175.                  * measuring movs from ROM to RAM
  176.                  * and subtracting RAM write time
  177.                  * as above.
  178.                  */
  179.  
  180.                 raw = bromtime(count) - brw;
  181.                 acctime[4] += raw/(TIMER2_RATE*count);
  182.  
  183.                 /*
  184.                  * Make similar measurements for
  185.                  * word operations.
  186.                  */
  187.  
  188.                 wrw = wstotime(count);
  189.                 acctime[3] += raw/(TIMER2_RATE*count);
  190.                 raw = wmvstime(count) - wrw;
  191.                 acctime[1] += raw/(TIMER2_RATE*count);
  192.                 raw = wromtime(count) - wrw;
  193.                 acctime[5] += raw/(TIMER2_RATE*count);
  194.  
  195.                 /*
  196.                  * If EMM is present, do measurements
  197.                  * on it using the same techniques.
  198.                  */
  199.  
  200.                 if (emmok) {
  201.  
  202.                         /*
  203.                          * Measure byte write,
  204.                          * calculate byte read.
  205.                          */
  206.  
  207.                         brw = bemstime(count);
  208.                         acctime[12] += brw/(TIMER2_RATE*count);
  209.                         raw = bemmtime(count) - brw;
  210.                         acctime[10] += raw/(TIMER2_RATE*count);
  211.  
  212.                         /*
  213.                          * Measure word write,
  214.                          * calculate word read.
  215.                          */
  216.  
  217.  
  218.                         wrw = wemstime(count);
  219.                         acctime[13] += raw/(TIMER2_RATE*count);
  220.                         raw = wemmtime(count) - wrw;
  221.                         acctime[11] += raw/(TIMER2_RATE*count);
  222.                 }
  223.  
  224.                 /*
  225.                  * Measure byte and word writes
  226.                  * into video RAM (assuming CGA adapter.)
  227.                  */
  228.  
  229.                 raw = bvidtime(count);
  230.                 acctime[6] += raw/(TIMER2_RATE*count);
  231.                 raw = wvidtime(count);
  232.                 acctime[7] += raw/(TIMER2_RATE*count);
  233.         }
  234.  
  235.         /*
  236.          * Calculate averages for all measurements.
  237.          */
  238.  
  239.         for (i = 0; i < vars; i++)
  240.                 acctime[i] /= trials;
  241.  
  242.         /*
  243.          * Release EMM memory page.
  244.          */
  245.  
  246.         if (emmok)
  247.                 finish_emm();
  248.  
  249.         /*
  250.          * Calculate numeric processor clock
  251.          * rate using floating point divide
  252.          * instructions, using the same
  253.          * technique as was used to measure
  254.          * the processor clock rate.
  255.          */
  256.         if (ndpok) {
  257.  
  258.                 fprate = 0;
  259.                 for (i = 0; i < trials; i++) {
  260.                         raw = fptime(FPCOUNT);
  261.                         fpacc +=  (raw / TIMER2_RATE - FPOVH) /
  262.                                 FPCLKS / FPCOUNT;
  263.                 }
  264.                 fpacc /= trials;
  265.                 fprate = 1.0/fpacc;
  266.         }
  267.  
  268.         /*
  269.          * Display the basic measurement results and
  270.          * performance index relative to a 6 MHz AT.
  271.          */
  272.  
  273.         printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
  274.         printf("ATPERF -- PC Tech Journal AT Hardware ");
  275.         printf("Performance Test\n");
  276.         printf("Version 1.00, Copyright (c) 1986 PC Tech ");
  277.         printf("Journal\n");
  278.         printf("IBM PC/AT model 339 (8 MHz) = 1.00 for relative ");
  279.         printf("measurements.\n                            ");
  280.         printf("      Byte             Word       Relative\n");
  281.  
  282.         printf("Average RAM instr. fetch:   ");
  283.         printf("                 ");
  284.         printf("%10.3g uS", acctime[8]);
  285.         printf("%10.2g\n", 0.403/acctime[8]);
  286.  
  287.         printf("Average RAM read time:      ");
  288.         printf("%10.3g uS    ", acctime[0]);
  289.         printf("%10.3g uS", acctime[1]);
  290.         printf("%10.2g\n", 0.401/acctime[1]);
  291.  
  292.         printf("Average RAM write time:     ");
  293.         printf("%10.3g uS    ", acctime[2]);
  294.         printf("%10.3g uS", acctime[3]);
  295.         printf("%10.2g\n", 0.401/acctime[3]);
  296.  
  297.         if (emmok) {
  298.                 printf("Average EMM read time:      ");
  299.                 printf("%10.3g uS    ", acctime[10]);
  300.                 printf("%10.3g uS", acctime[11]);
  301.                 printf("%10.2g\n", 0.402/acctime[11]);
  302.  
  303.                 printf("Average EMM write time:     ");
  304.                 printf("%10.3g uS    ", acctime[12]);
  305.                 printf("%10.3g uS", acctime[13]);
  306.                 printf("%10.2g\n", 0.402/acctime[13]);
  307.         }
  308.         printf("Average ROM read time:      ");
  309.         printf("%10.3g uS    ", acctime[4]);
  310.         printf("%10.3g uS", acctime[5]);
  311.         printf("%10.2g\n", 0.401/acctime[5]);
  312.  
  313.         printf("Average Video write time:   ");
  314.         printf("%10.3g uS    ", acctime[6]);
  315.         printf("%10.3g uS", acctime[7]);
  316.         printf("%10.2g\n", 2.415/acctime[7]);
  317.  
  318.         printf("\nClock rate:                   ");
  319.         printf("%4.1g MHz", clkrate);
  320.         printf("  Relative: %4.2g\n", clkrate/8.0);
  321.  
  322.         if (ndpok) {
  323.                 printf("Numeric processor clock rate: ");
  324.                 printf("%4.1g MHz", fprate);
  325.                 printf("  Relative: %4.2g\n", fprate/5.33);
  326.         }
  327.  
  328.         /*
  329.          * Calculate refresh overhead from instruction
  330.          * fetch time by assuming that each fetch takes
  331.          * an exact multiple of the clock period.  The
  332.          * difference between average time and the time
  333.          * for an individual fetch is due to memory
  334.          * refresh cycles.
  335.          */
  336.  
  337.         raw = acctime[0] / clktime;
  338.         printf("Refresh overhead:              %2.1g%%\n",
  339.                 ( (raw - (int)raw) / (int)raw ) * 100);
  340.  
  341.         /*
  342.          * Print information about the memory based
  343.          * on the speed measurements.
  344.          */
  345.  
  346.         printf("\nMemory   ");
  347.         printf("       Access width          Wait states\n");
  348.         analyze("RAM read", acctime[0], acctime[1]);
  349.         analyze("RAM write", acctime[2], acctime[3]);
  350.         if (emmok) {
  351.                 analyze("EMM read", acctime[10], acctime[11]);
  352.                 analyze("EMM write", acctime[12], acctime[13]);
  353.         }
  354.         analyze("ROM read", acctime[4], acctime[5]);
  355.         analyze("Video write", acctime[6], acctime[7]);
  356. }
  357.  
  358. /*
  359.  * analyze
  360.  *
  361.  * This procedure deduces information about the memory based on
  362.  * the measured times.
  363.  * If byte (8 bits) and word (16 bits) times are different then
  364.  * the memory is byte oriented since each word operation takes
  365.  * two byte operations.  Otherwise, if the byte and word
  366.  * times are about the same, the memory is word oriented and can
  367.  * access either a word or a byte in a single memory cycle.
  368.  *
  369.  * Each memory access takes an exact number of processor clock
  370.  * cycles.  The first two are required by the processor, but
  371.  * any additional cycles are determined by the memory and are
  372.  * called wait states (because the processor is waiting for
  373.  * the memory.)
  374.  */
  375.  
  376. analyze(name, btime, wtime)
  377.         char    *name;
  378.         double  btime;
  379.         double  wtime;
  380. {
  381.  
  382.         /*
  383.          * Print the heading
  384.          */
  385.  
  386.         printf("%-12s", name);
  387.  
  388.         /*
  389.          * Determine whether the memory is byte
  390.          * oriented, word oriented, or neither.
  391.          * (If neither, the data are suspect.)
  392.          */
  393.  
  394.         if (btime > wtime*0.75 &&
  395.             btime < wtime*1.25)
  396.                 printf("        Word  ");
  397.         else if (btime*2 > wtime*0.75 &&
  398.                  btime*2 < wtime*1.25)
  399.                 printf("        Byte  ");
  400.         else
  401.                 printf("       Strange");
  402.  
  403.         /*
  404.          * Determine the number of wait states
  405.          * by subtracting two processor clock times,
  406.          * dividing by the clock period,
  407.          * and rounding down to an integer.
  408.          */
  409.  
  410.         printf("              %6.0f\n",
  411.                (btime - 2*clktime) / clktime);
  412. }
  413.